<?
// Standardised search capability
// (nowadays would be done via auto-completion)
// Written by John Shepherd, May 2004
// Assumes that all other libraries are loaded

# runSearch:
# - takes a db handle and a query string
# - returns the # matching tuples and an array containing those tuple

function runSearch($db, $query)
{
	$res = dbQuery($db,$query);
	$matches = array();
	$nmatches = 0;
	while ($tup = dbNext($res)) {
		$matches[] = $tup;
		$nmatches++;
	}
	return array($nmatches,$matches);
}

# navigator:
# - navigates through search results in blocks of size $n (default:20)
# - produces a tailored drop-down menu to move backwards/forwards
# - "onChange" doesn't appear to work on Explorer ... oh, well

function navigator($starting, $nItems, $style, $n=20)
{
	$choices = array();
	$nLeft = $nItems - $starting;
	if ($nItems <= $n) return "All";
	if ($nLeft <= $n)
		$choices["Last $nLeft"] = $starting;
	elseif ($starting == 0)
		$choices["First $n"] = $starting;
	else
		$choices["Current $n"] = $starting;
	if ($starting >= $n) {
		if ($starting >= (2*$n)) $choices["First $n"] = 0;
		$choices["Previous $n"] = $starting-$n;
	}
	elseif ($starting > 0)
		$choices["First $n"] = 0;
	if ($nLeft > $n) {
		$nnLeft = $nItems - ($starting+$n);
		if ($nnLeft > $n) $nnLeft = $n;
		$choices["Next $nnLeft"] = $starting+$n;
		if ($nLeft > (2*$n))
			$choices["Last $n"] = $nItems-$n;
	}
	$handler = "onChange='submit();'";
	return selectFromList("starting",$starting,$choices,$style,$handler);
}

// searchResults:
// - produces HTML for a standardised search page
// - parameters are:
//   array of results from search query
//   headings to display at top of results table
//   fields to display within results table
//      (assume also that a field called id is returned by the query)
//   field on which to place the link to view more details
//   returningIDs: is this page being used to return id values to another page
//   name of form in invoking page (window.opener)
//   name of field "ff" to be set in invoking page
//      (also sets another field called "ff_shown")
//   field which is being returned to invoker (if any)

function searchResults($results, $headings, $displayed, $linked,
			$returningIDs, $form, $field, $returned)
{
	if (is_string($results)) return $results;
	if (!is_array($results)) return "";

	$html = "<table cellpadding=6><tr bgcolor='#AAAAAA'>";
	foreach ($headings as $heading) $html .= "<th>$heading</th>";
	$html .= "</tr>\n";
	for ($i = 0; $i < count($results); $i++)
	{
		$fields = $results[$i];
		$html .= "<tr>";
		foreach ($displayed as $fname) {
			$value = $fields[$fname];
			if ($fname == $linked)
				$value = "<a href='view.php?id=".
					 "$fields[id]'>$value</a>";
			$html .= "<td class='ul'>$value</td>";
		}
		// only provide select buttons if returning IDs
		if ($returningIDs) {
			$html .= "<td>".
				 selectButton($form,$field,$fields['id'],
				 			$fields[$returned]).
				 "</td>";
			
		}
		$html .= "</tr>\n";
	}
	$html .= "</table>";
	return $html;
}

// selectButton:
// - generate a button that can send selected value back to invoker
// - requires JavaScript

function selectButton($form,$field,$id,$val)
{
return <<<BUTTON
<input type='button' value='Select' style='font-size:6pt'
 onclick="window.opener.document.$form.$field.value='$id';
 	  window.opener.document.$form.${field}_shown.value='$val';
	  window.opener.focus(); window.close(); return true;">
BUTTON;
}

# selectButton:
# - generate a button that can send selected value back to invoker

function selectLink($form,$field,$id,$val,$text)
{
return <<<LINK
<a href='#'
onclick="window.opener.document.$form.$field.value='$id';
window.opener.document.$form.${field}_shown.value='$val';
window.opener.focus(); window.close(); return true;">$text</a>
LINK;
}

# limits:
# - specify limits on how many results of a search to display
# - can be first 20, first 50, last 20, last 50, or all

function limits($lim)
{
	$lims = array("first 20"=>20, "first 50"=>50,
			"last 50"=>-50, "last 20"=> -20,
			"[All]"=>999999);
	$style = "color:green";
	$handler = "onChange='submit();'";
	return selectFromList("limit",$lim,$lims,$style,$handler);
}

# wordFilter:
# - takes a string of one or more words and an array of field names
# - returns an expression which checks whether every word appears
#   in at least one field (using case-insensitive matching)

function wordFilter($keys, $fields)
{
	$filters = array();
        $keys = preg_split("/[\s,]+/",trim($keys));
	$allFields = array();
	foreach ($fields as $f) $allFields[] = "coalesce($f::text,'')";
	$alltext = join("||' '||",$allFields);
        foreach ($keys as $key) {
		# Quick fix for one common regexp bug
		if ($key == "*") $key = ".*";
		# PHP has no support for checking POSIX RegExps
		# So we try an approximate hack like this ...
		$check = @preg_match("/$key/","abc");
		if ($check === false) continue;
		# ... which ignores invalid Perl regexps
                $filters[] = mkSQL("(($alltext) ~* %s)",$key);
	}
	return $filters;
}

?>
